/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Optimizacion;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * @author REI
 */
public class ListaBloques {
    
    private NodoBloque inicio;
    private NodoBloque ultimo;
    
    public ListaBloques() {
        inicio = null;
        ultimo = null;
    }

    public void add(NodoBloque nodo) {
        NodoBloque aux = nodo;
        if (inicio == null) {
            inicio = aux;
            ultimo = aux;
        } else {
            ultimo.setSiguiente(aux);
            ultimo = aux;
        }
    }

    public void enlazar_bloques(ListaBloques grafo) {
        inicio = grafo.getInicio();
        NodoBloque aux = inicio;
        while (aux != null) {

            if (aux.getEtqV() == null && aux.getEtqF() == null) {//si no tiene etiqueta a donde ir,
                //no termino ni con un IF, ni GOTO
                aux.setPtr_etqF(aux.getSiguiente());
            } else {
                if (aux.getEtqV() != null && aux.getEtqF() != null) {//significa q tiene etqV, etqF 
                    //es por IF & GOTO
                    aux.setPtr_etqV(buscar(aux.getEtqV()));
                    aux.setPtr_etqF(buscar(aux.getEtqF()));
                } else {
                    if (aux.getEtqV() != null) {//significa q tiene etqV 
                        //es por IF
                        aux.setPtr_etqV(buscar(aux.getEtqV()));
                        aux.setPtr_etqF(aux.getSiguiente());
                    } else {
                        if (aux.getEtqF() != null) {
                            //es por GOTO
                            aux.setPtr_etqF(buscar(aux.getEtqF()));
                        }
                    }
                }
            }
            aux = aux.getSiguiente();
        }

        //se procede a eliminar los apuntadores siguiente
        eliminar_apuntador_siguiente();

    }

    public void imprimir_grafo(ListaBloques grafo, java.io.FileOutputStream Archivo) throws IOException {
        inicio = grafo.getInicio();
        NodoBloque aux = inicio;
        

                while (aux != null) {

                    if (aux.getEtqV() == null && aux.getEtqF() == null) {//si no tiene etiqueta a donde ir,
                        //no termino ni con un IF, ni GOTO
                        aux.setPtr_etqV(aux.getSiguiente());
                        if (aux.getSiguiente() != null) {
                           // System.out.println(aux.getNumero() + " -> " + aux.getSiguiente().getNumero());
                            Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                            Archivo.write(("B" + aux.getNumero() + ":f1 -> B" + aux.getSiguiente().getNumero() + ":here;\n").getBytes());
                        }
                    } else {
                        if (aux.getEtqV() != null && aux.getEtqF() != null) {//significa q tiene etqV, etqF 
                            //es por IF & GOTO
                            NodoBloque coincide = buscar(aux.getEtqV());
                            if (coincide != null) {
                               // System.out.println(aux.getNumero() + " -> " + coincide.getNumero());

                                //Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + aux.getNumero() + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                Archivo.write(("B" + aux.getNumero() + ":f1 -> B" + coincide.getNumero() + ":here;\n").getBytes());
                            }
                            //aux.setPtr_etqV(coincide);

                            coincide = buscar(aux.getEtqF());
                            if (coincide != null) {
                               // System.out.println(aux.getNumero() + " -> " + coincide.getNumero());
                                //Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + aux.getNumero() + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                Archivo.write(("B" + aux.getNumero() + ":f0 -> B" + coincide.getNumero() + ":here;\n").getBytes());
                            }
                            //aux.setPtr_etqF(coincide);
                        } else {
                            if (aux.getEtqV() != null) {//significa q tiene etqV 
                                //es por IF
                                NodoBloque coincide = buscar(aux.getEtqV());
                                if (coincide != null) {
                                   // System.out.println(aux.getNumero() + " -> " + coincide.getNumero());
                                    //Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + aux.getNumero() + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                    Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                    Archivo.write(("B" + aux.getNumero() + ":f1 -> B" + coincide.getNumero() + ":here;\n").getBytes());
                                }
                                //aux.setPtr_etqV(coincide);


                                if (aux.getSiguiente() != null) {
                                    //System.out.println(aux.getNumero() + " -> " + aux.getSiguiente().getNumero());
                                    //Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + aux.getNumero() + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                    Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                    Archivo.write(("B" + aux.getNumero() + ":f0 -> B" + aux.getSiguiente().getNumero() + ":here;\n").getBytes());
                                }
                                //aux.setPtr_etqF(aux.getSiguiente());
                            } else {
                                if (aux.getEtqF() != null) {
                                    //es por GOTO
                                    NodoBloque coincide = buscar(aux.getEtqF());
                                    if (coincide != null) {
                                        //System.out.println(aux.getNumero() + " -> " + coincide.getNumero());
                                        //Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + aux.getNumero() + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                        Archivo.write(("B" + aux.getNumero() + "[label  = \"{<here>" + get_etiquetas(aux) + "|" + get_cuerpo_bloque(aux) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
                                        Archivo.write(("B" + aux.getNumero() + ":f0 -> B" + coincide.getNumero() + ":here;\n").getBytes());
                                    }
                                    //aux.setPtr_etqF(coincide);
                                }
                            }
                        }
                    }
                    aux = aux.getSiguiente();
                }

                if(grafo.getUltimo()!=null) {
            Archivo.write(("B" + grafo.getUltimo().getNumero() + "[label  = \"{<here>" + get_etiquetas(grafo.getUltimo()) + "|" + get_cuerpo_bloque(grafo.getUltimo()) + "|{<f0> etqF|<f1> etqV}}\"];\n\n").getBytes());
        }

    }

    public String get_cuerpo_bloque(NodoBloque bloque) {
        String texto = "";

        Iterator it = bloque.getLineas_codigo().iterator();

        while (it.hasNext()) {      
            texto = texto.replace(">", "&gt;"); 
            texto = texto.replace(">=", "&lt;="); 
            texto = texto.replace("<", "&lt;"); 
            texto = texto.replace("<=", "&lt;="); 
            texto = texto.replace("<-", "&lt;-"); 
            
           
            
            
            
            
            texto = texto + it.next() + "\\l";
            
            if(texto.contains("imprimir"))
            {
                texto= texto.replace("\"", "");
            }
        }
        return texto;
    }
    
    public String get_cuerpo_bloque_saltoLn(NodoBloque bloque) {
        String texto = "";

        Iterator it = bloque.getLineas_codigo().iterator();

        while (it.hasNext()) {
            if(texto.contains("imprimir(\\n)"))
            {
                texto = texto.replace("imprimir(\\n)", "imprimir()");
            }
            texto = texto + it.next() + "\n";
        }
        return texto;
    }
    
    public String get_etiquetas(NodoBloque bloque){
        String etq = "";
        if (!bloque.getEtiquetas().isEmpty()) {
            etq = bloque.getEtiquetas().get(0).toString();

            for (int i = 1; i < bloque.getEtiquetas().size(); i++) {
                etq = etq + " , " + bloque.getEtiquetas().get(i);
            }
            etq = etq + ":\\l";
            
            if(etq.contains("imprimir(\\n)"))
            {
                etq = etq.replace("imprimir(\\n)", "imprimir()");
            }
        }
        return etq;
        
    }
    
    public String get_etiquetas_saltoLn(NodoBloque bloque){
        String etq = "";
        if (!bloque.getEtiquetas().isEmpty()) {
            etq = bloque.getEtiquetas().get(0).toString();

            for (int i = 1; i < bloque.getEtiquetas().size(); i++) {
                etq = etq + " , " + bloque.getEtiquetas().get(i);
            }
            etq = etq + ":\n";
        }
        return etq;
        
    }

    public NodoBloque buscar(String etiqueta) {
        NodoBloque aux = inicio;
        while (aux != null) {
            ArrayList lista_etq = aux.getEtiquetas();
            Iterator it = lista_etq.iterator();
            boolean coincide = false;
            while (it.hasNext()) {
                if (etiqueta.compareTo(it.next().toString()) == 0) {
                    coincide = true;
                }
            }

            if (coincide) {
                return aux;
            } else {
                aux = aux.getSiguiente();
            }
        }
        return null;
    }

    public void eliminar_apuntador_siguiente() {
        NodoBloque aux = inicio;
        NodoBloque aux2;
        while (aux != null) {
            aux2 = aux.getSiguiente();
            aux.setSiguiente(null);
            aux = aux2;
        }
    }

    /**
     * @return the inicio
     */
    public NodoBloque getInicio() {
        return inicio;
    }

    /**
     * @param inicio the inicio to set
     */
    public void setInicio(NodoBloque inicio) {
        this.inicio = inicio;
    }

    /**
     * @return the ultimo
     */
    public NodoBloque getUltimo() {
        return ultimo;
    }

    /**
     * @param ultimo the ultimo to set
     */
    public void setUltimo(NodoBloque ultimo) {
        this.ultimo = ultimo;
    }
    
}
